﻿#include "window.h"

QWindow::QWindow(QWidget *parent) : QMainWindow(parent)
{
    this->resize(Width, Hight);
    this->setWindowTitle(QString::fromLocal8Bit("Mr.Harold SerialPort Assisant"));
    SetStyleWindow(styleFilePath);
    SetWidgets();
    SerialObjectInit();
}

QWindow::~QWindow()
{
}

/**
 * @brief 初始化串口对象与定时器外设
 * 
 */
void QWindow::SerialObjectInit(void)
{
    // 创建串口对象
    serial = new QSerialPort(this);

    // 获取本机活动的串口数据并存在链表中
    GetAvaliablePortName();

    // 定时刷新
    serialTimer = new QTimer(this);
    serialTimer->setInterval(1000); // 每隔1秒刷新一次
    connect(serialTimer, &QTimer::timeout, this, &QWindow::FlushSerialPort);
    serialTimer->start();
}

/**
 * @brief 初始化按钮等外设组件
 * 
 */
void QWindow::SetWidgets(void)
{
    quint16 x0 = 10;
    quint16 y0 = Hight / 10;
    quint16 x_pos = 60;
    quint16 y_pos = Hight / 10;
    quint16 ComboBox_len = 180;
    quint16 ComboBox_hight = 40;
    quint16 label_len = 50;
    quint16 label_hight = 40;

    SerialPortNum = new QComboBox(this);
    SerialPortNumLabel = new QLabel(this);
    SerialBaudRate = new QComboBox(this);
    SerialBaudRateLabel = new QLabel(this);
    SerialDataBits = new QComboBox(this);
    SerialDataBitsLabel = new QLabel(this);
    SerialStopBits = new QComboBox(this);
    SerialStopBitsLabel = new QLabel(this);
    SerialParityBits = new QComboBox(this);
    SerialParityBitsLabel = new QLabel(this);
    SerialFlowConstrol = new QComboBox(this);
    SerialFlowConstrolLabel = new QLabel(this);
    connectButton = new QPushButton(this);
    
    /* 串口号设置 */
    SerialPortNum->setGeometry(x_pos,
                               0 * (y_pos) + 5,
                               ComboBox_len,
                               ComboBox_hight);
    SerialPortNumLabel->setGeometry(x0,
                                    0 * (y0) + 5,
                                    label_len,
                                    label_hight);
    SerialPortNumLabel->setText("串口号");

    /* 波特率设置 */
    SerialBaudRate->setGeometry(x_pos,
                                1 * (y_pos) + 5,
                                ComboBox_len,
                                ComboBox_hight);
    SerialBaudRateLabel->setGeometry(x0,
                                     1 * (y0) + 5,
                                     label_len,
                                     label_hight);
    SerialBaudRateLabel->setText("波特率");

    /* 数据位设置 */
    SerialDataBits->setGeometry(x_pos,
                                2 * (y_pos) + 5,
                                ComboBox_len,
                                ComboBox_hight);
    SerialDataBitsLabel->setGeometry(x0,
                                     2 * (y0) + 5,
                                     label_len,
                                     label_hight);
    SerialDataBitsLabel->setText("数据位");

    /* 停止位设置 */
    SerialStopBits->setGeometry(x_pos,
                                3 * (y_pos) + 5,
                                ComboBox_len,
                                ComboBox_hight);
    SerialStopBitsLabel->setGeometry(x0,
                                     3 * (y0) + 5,
                                     label_len,
                                     label_hight);
    SerialStopBitsLabel->setText("停止位");

    /* 检验位设置 */
    SerialParityBits->setGeometry(x_pos,
                                  4 * (y_pos) + 5,
                                  ComboBox_len,
                                  ComboBox_hight);
    SerialParityBitsLabel->setGeometry(x0,
                                       4 * (y0) + 5,
                                       label_len,
                                       label_hight);
    SerialParityBitsLabel->setText("检验位");

    /* 流控设置 */
    SerialFlowConstrol->setGeometry(x_pos,
                                    5 * (y_pos) + 5,
                                    ComboBox_len,
                                    ComboBox_hight);
    SerialFlowConstrolLabel->setGeometry(x0,
                                         5 * (y0) + 5,
                                         label_len,
                                         label_hight);
    SerialFlowConstrolLabel->setText("流控");

    /* 连接串口按钮 */
    connectButton->setGeometry(0,
                               6 * (y_pos) + 20,
                               ComboBox_len + x_pos,
                               ComboBox_hight);
    connectButton->setText("连接串口");

    SerialPortNumInit();
    SerialBaudRateInit();
    SerialDataBitsInit();
    SerialStopBitsInit();
    SerialParityBitsInit();
    SerialFlowConstrolInit();
}

/**
 * @brief 智能识别本机活动的串口
 *
 */
void QWindow::GetAvaliablePortName(void)
{
    // 获取本机活动的串口数据并存在链表中
    // 智能识别本机活动的串口
    serial_port = QSerialPortInfo::availablePorts();
    int count = serial_port.count();
    for (int i = 0; i < count; i++)
    {
        // 将活动的串口数据保存在链表中
        QSerialPortInfo info = serial_port.at(i);
        SerialPortNum->addItem(info.portName() + " " + info.description());
    }
}

/**
 * @brief 比较两个串口列表是否不同,此为槽函数
 *
 * @param newPorts
 * @param oldPorts
 * @return true
 * @return false
 */
bool QWindow::isPortsChanged(const QList<QSerialPortInfo> &newPorts,
                             const QList<QSerialPortInfo> &oldPorts)
{
    // 数量不同则直接判定为变化
    if (newPorts.count() != oldPorts.count())
    {
        return true;
    }

    // 数量相同则比较每个端口名
    for (int i = 0; i < newPorts.count(); ++i)
    {
        // 端口名是串口的唯一标识
        if (newPorts[i].portName() != oldPorts[i].portName())
        {
            return true;
        }
    }

    return false;
}

/**
 * @brief 刷新可活动的串口号
 * 
 */
void QWindow::FlushSerialPort(void)
{
    // 避免在串口打开状态下刷新（可选，根据需求调整）
    if (serial->isOpen())
    {
        return;
    }

    QList<QSerialPortInfo> newPorts = QSerialPortInfo::availablePorts();

    // 比较新列表与旧列表是否有变化
    if (isPortsChanged(newPorts, serial_port))
    {
        // 清空下拉框并添加新列表
        SerialPortNum->clear();

        if (newPorts.isEmpty())
        {
            SerialPortNum->addItem("无可用串口");
        }
        else
        {
            foreach (const QSerialPortInfo &info, newPorts)
            {
                QString description = info.description().isEmpty()
                                          ? QString::fromLocal8Bit("未知设备")
                                          : info.description();
                QString portItem = QString("%1 (%2)")
                                       .arg(info.portName())
                                       .arg(description);
                SerialPortNum->addItem(portItem, info.portName());
            }
        }

        // 更新存储的列表
        serial_port = newPorts;
    }
}

/**
 * @brief 设置串口风格
 * 
 * @param filepath 
 */
void QWindow::SetStyleWindow(QString filepath)
{
    QFile *styleFile;
    styleFile = new QFile(filepath, this); // 获取资源文件的对象
    styleFile->open(QFile::ReadOnly);                   // 只读模式
    QString styleSheet = QString(styleFile->readAll()); // 读出的数据转成字符串
    this->setStyleSheet(styleSheet);
    styleFile->close(); // 最后关闭这个文件
}

void QWindow::SerialPortNumInit(void)
{

}

void QWindow::SerialBaudRateInit(void)
{

}

void QWindow::SerialDataBitsInit(void)
{

}

void QWindow::SerialStopBitsInit(void)
{

}

void QWindow::SerialParityBitsInit(void)
{

}

void QWindow::SerialFlowConstrolInit(void)
{

}
